import { Injectable, ConflictException, NotFoundException, UnauthorizedException, BadRequestException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import * as bcrypt from 'bcrypt';
import { User, UserRole } from './schemas/user.schema';
import { UserSetting } from './schemas/user-setting.schema';
import { Artwork } from './schemas/artwork.schema';
import { CreateUserDto } from './dto/create-user.dto';
import { LoginUserDto } from './dto/login-user.dto';
import { UpdateUserDto, ChangePasswordDto } from './dto/update-user.dto';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class UsersService {
    // 短信验证码缓存
    private smsCodeCache = new Map<string, { code: string; expireAt: number }>();

    constructor(
        @InjectModel(User.name) private userModel: Model<User>,
        @InjectModel(UserSetting.name) private userSettingModel: Model<UserSetting>,
        @InjectModel(Artwork.name) private artworkModel: Model<Artwork>,
        private jwtService: JwtService,
    ) { }

    // 创建用户
    async create(createUserDto: CreateUserDto): Promise<User> {
        const { username, email, password } = createUserDto;

        // 检查用户名和邮箱是否已存在
        const existingUser = await this.userModel.findOne({
            $or: [{ username }, { email }],
        });

        if (existingUser) {
            if (existingUser.username === username) {
                throw new ConflictException('用户名已被使用');
            } else {
                throw new ConflictException('邮箱已被使用');
            }
        }

        // 加密密码
        const hashedPassword = await bcrypt.hash(password, 10);

        // 创建新用户
        const newUser = new this.userModel({
            ...createUserDto,
            password: hashedPassword,
            roles: [UserRole.USER],
        });

        const savedUser = await newUser.save();

        // 创建用户设置
        await this.userSettingModel.create({
            user_id: savedUser._id,
        });

        return savedUser;
    }

    // 用户登录
    async login(loginUserDto: LoginUserDto): Promise<{ token: string; user: User }> {
        const { username, password, phone, sms_code, wechat_code, login_type } = loginUserDto;
        let user: User = null;

        // 根据登录类型处理不同的登录方式
        if (login_type === 'phone' || (phone && sms_code)) {
            // 手机号登录
            user = await this.loginByPhone(phone, sms_code);
        } else if (login_type === 'wechat' || wechat_code) {
            // 微信登录
            user = await this.loginByWechat(wechat_code);
        } else {
            // 用户名/邮箱登录
            user = await this.loginByUsername(username, password);
        }

        if (!user) {
            throw new UnauthorizedException('登录失败');
        }

        // 生成JWT令牌
        const token = this.jwtService.sign({
            sub: user._id,
            username: user.username,
            roles: user.roles,
        });

        return { token, user };
    }

    // 用户名/邮箱登录
    async loginByUsername(username: string, password: string): Promise<User> {
        // 查找用户（支持用户名或邮箱登录）
        const user = await this.userModel.findOne({
            $or: [{ username }, { email: username }],
        });

        if (!user) {
            throw new NotFoundException('用户不存在');
        }

        // 验证密码
        const isPasswordValid = await bcrypt.compare(password, user.password);
        if (!isPasswordValid) {
            throw new UnauthorizedException('密码错误');
        }

        return user;
    }

    // 手机号登录
    async loginByPhone(phone: string, smsCode: string): Promise<User> {
        // 验证短信验证码
        const isCodeValid = await this.verifySmsCode(phone, smsCode);
        if (!isCodeValid) {
            throw new UnauthorizedException('验证码错误或已过期');
        }

        // 查找用户
        let user = await this.userModel.findOne({ phone });

        // 如果用户不存在，自动创建用户
        if (!user) {
            const randomUsername = `user_${Date.now()}${Math.floor(Math.random() * 1000)}`;
            const randomPassword = Math.random().toString(36).slice(-8);
            const hashedPassword = await bcrypt.hash(randomPassword, 10);

            user = new this.userModel({
                username: randomUsername,
                email: `${randomUsername}@example.com`, // 临时邮箱
                password: hashedPassword,
                phone,
                phone_verified: true,
                roles: [UserRole.USER],
            });

            await user.save();

            // 创建用户设置
            await this.userSettingModel.create({
                user_id: user._id,
            });
        }

        return user;
    }

    // 微信登录
    async loginByWechat(code: string): Promise<User> {
        // 获取微信用户信息
        const wechatUserInfo = await this.getWechatUserInfo(code);
        if (!wechatUserInfo) {
            throw new UnauthorizedException('微信授权失败');
        }

        const { openid, unionid, nickname, headimgurl } = wechatUserInfo;

        // 查找用户
        let user = await this.userModel.findOne({
            $or: [{ wechat_openid: openid }, { wechat_unionid: unionid }],
        });

        // 如果用户不存在，自动创建用户
        if (!user) {
            const randomUsername = `wx_${Date.now()}${Math.floor(Math.random() * 1000)}`;
            const randomPassword = Math.random().toString(36).slice(-8);
            const hashedPassword = await bcrypt.hash(randomPassword, 10);

            user = new this.userModel({
                username: randomUsername,
                email: `${randomUsername}@example.com`, // 临时邮箱
                password: hashedPassword,
                nickname: nickname || '微信用户',
                avatar: headimgurl || '',
                wechat_openid: openid,
                wechat_unionid: unionid,
                roles: [UserRole.USER],
            });

            await user.save();

            // 创建用户设置
            await this.userSettingModel.create({
                user_id: user._id,
            });
        }

        return user;
    }

    // 发送短信验证码
    async sendSmsCode(phone: string): Promise<boolean> {
        // 生成6位随机验证码
        const code = Math.floor(100000 + Math.random() * 900000).toString();

        // 在实际项目中，这里应该调用短信服务发送验证码
        // 为了演示，我们只是将验证码存储在Redis中

        // 设置验证码有效期为5分钟
        const EXPIRE_TIME = 60 * 5;

        // 存储验证码到Redis或其他缓存系统
        // 这里使用模拟实现，实际项目中应该使用Redis等缓存系统
        this.smsCodeCache.set(phone, {
            code,
            expireAt: Date.now() + EXPIRE_TIME * 1000
        });

        console.log(`向手机号 ${phone} 发送验证码: ${code}`);

        return true;
    }

    // 验证短信验证码
    async verifySmsCode(phone: string, code: string): Promise<boolean> {
        // 从缓存中获取验证码
        const cachedData = this.smsCodeCache.get(phone);

        if (!cachedData) {
            return false; // 验证码不存在
        }

        if (Date.now() > cachedData.expireAt) {
            this.smsCodeCache.delete(phone); // 验证码已过期，删除
            return false;
        }

        if (cachedData.code !== code) {
            return false; // 验证码不匹配
        }

        // 验证成功后删除验证码，防止重复使用
        this.smsCodeCache.delete(phone);

        return true;
    }

    // 获取微信用户信息
    async getWechatUserInfo(code: string): Promise<any> {
        try {
            // 微信应用配置
            const appId = process.env.WECHAT_APP_ID || 'your_app_id';
            const appSecret = process.env.WECHAT_APP_SECRET || 'your_app_secret';

            // 获取access_token
            const tokenUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appId}&secret=${appSecret}&code=${code}&grant_type=authorization_code`;
            const tokenResponse = await fetch(tokenUrl);
            const tokenData = await tokenResponse.json();

            if (tokenData.errcode) {
                console.error('获取微信access_token失败:', tokenData.errmsg);
                return null;
            }

            const { access_token, openid } = tokenData;

            // 获取用户信息
            const userInfoUrl = `https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${openid}&lang=zh_CN`;
            const userInfoResponse = await fetch(userInfoUrl);
            const userInfo = await userInfoResponse.json();

            if (userInfo.errcode) {
                console.error('获取微信用户信息失败:', userInfo.errmsg);
                return null;
            }

            return userInfo;
        } catch (error) {
            console.error('微信登录异常:', error);
            return null;
        }
    }

    // 根据ID查找用户
    async findById(id: string): Promise<User> {
        const user = await this.userModel.findById(id);
        if (!user) {
            throw new NotFoundException('用户不存在');
        }
        return user;
    }

    // 根据用户名查找用户
    async findByUsername(username: string): Promise<User> {
        const user = await this.userModel.findOne({ username });
        if (!user) {
            throw new NotFoundException('用户不存在');
        }
        return user;
    }

    // 更新用户信息
    async update(id: string, updateUserDto: UpdateUserDto): Promise<User> {
        // 检查用户名和邮箱是否已被使用
        if (updateUserDto.username) {
            const existingUserWithUsername = await this.userModel.findOne({
                username: updateUserDto.username,
                _id: { $ne: id },
            });
            if (existingUserWithUsername) {
                throw new ConflictException('用户名已被使用');
            }
        }

        if (updateUserDto.email) {
            const existingUserWithEmail = await this.userModel.findOne({
                email: updateUserDto.email,
                _id: { $ne: id },
            });
            if (existingUserWithEmail) {
                throw new ConflictException('邮箱已被使用');
            }
        }

        const updatedUser = await this.userModel.findByIdAndUpdate(
            id,
            updateUserDto,
            { new: true },
        );

        if (!updatedUser) {
            throw new NotFoundException('用户不存在');
        }

        return updatedUser;
    }

    // 修改密码
    async changePassword(
        id: string,
        changePasswordDto: ChangePasswordDto,
    ): Promise<User> {
        const { current_password, new_password } = changePasswordDto;

        const user = await this.userModel.findById(id);
        if (!user) {
            throw new NotFoundException('用户不存在');
        }

        // 验证当前密码
        const isPasswordValid = await bcrypt.compare(current_password, user.password);
        if (!isPasswordValid) {
            throw new UnauthorizedException('当前密码错误');
        }

        // 加密新密码
        const hashedPassword = await bcrypt.hash(new_password, 10);

        // 更新密码
        user.password = hashedPassword;
        return user.save();
    }

    // 获取用户设置
    async getUserSettings(userId: string): Promise<UserSetting> {
        let settings = await this.userSettingModel.findOne({ user_id: userId });

        if (!settings) {
            // 如果没有设置，创建默认设置
            settings = await this.userSettingModel.create({
                user_id: userId,
            });
        }

        return settings;
    }

    // 更新用户设置
    async updateUserSettings(
        userId: string,
        settingsData: Partial<UserSetting>,
    ): Promise<UserSetting> {
        let settings = await this.userSettingModel.findOne({ user_id: userId });

        if (!settings) {
            // 如果没有设置，创建新设置
            settings = await this.userSettingModel.create({
                user_id: userId,
                ...settingsData,
            });
        } else {
            // 更新现有设置
            Object.assign(settings, settingsData);
            await settings.save();
        }

        return settings;
    }

    // 添加作品到收藏
    async favoriteArtwork(userId: string, artworkId: string): Promise<User> {
        const user = await this.userModel.findById(userId);
        if (!user) {
            throw new NotFoundException('用户不存在');
        }

        const artwork = await this.artworkModel.findById(artworkId);
        if (!artwork) {
            throw new NotFoundException('作品不存在');
        }

        // 检查是否已收藏
        if (user.favorited_works.includes(artworkId)) {
            throw new BadRequestException('已经收藏过该作品');
        }

        // 添加到收藏
        user.favorited_works.push(artworkId);
        return user.save();
    }

    // 从收藏中移除作品
    async unfavoriteArtwork(userId: string, artworkId: string): Promise<User> {
        const user = await this.userModel.findById(userId);
        if (!user) {
            throw new NotFoundException('用户不存在');
        }

        // 检查是否已收藏
        if (!user.favorited_works.includes(artworkId)) {
            throw new BadRequestException('未收藏该作品');
        }

        // 从收藏中移除
        user.favorited_works = user.favorited_works.filter(
            (id) => id !== artworkId,
        );

        return user.save();
    }

    // 获取用户收藏的作品
    async getFavoritedArtworks(userId: string): Promise<Artwork[]> {
        const user = await this.userModel.findById(userId);
        if (!user) {
            throw new NotFoundException('用户不存在');
        }

        return this.artworkModel.find({
            _id: { $in: user.favorited_works },
        });
    }

    // 获取用户创建的作品
    async getUserArtworks(userId: string): Promise<Artwork[]> {
        return this.artworkModel.find({ user_id: userId });
    }

    // 保存用户创建的作品
    async saveArtwork(artworkData: Partial<Artwork>): Promise<Artwork> {
        const newArtwork = new this.artworkModel(artworkData);
        return newArtwork.save();
    }

    // 更新作品信息
    async updateArtwork(
        artworkId: string,
        userId: string,
        updateData: Partial<Artwork>,
    ): Promise<Artwork> {
        const artwork = await this.artworkModel.findById(artworkId);

        if (!artwork) {
            throw new NotFoundException('作品不存在');
        }

        // 检查是否是作品所有者
        if (artwork.user_id.toString() !== userId) {
            throw new UnauthorizedException('无权修改该作品');
        }

        // 更新作品
        Object.assign(artwork, updateData);
        return artwork.save();
    }

    // 删除作品
    async deleteArtwork(artworkId: string, userId: string): Promise<void> {
        const artwork = await this.artworkModel.findById(artworkId);

        if (!artwork) {
            throw new NotFoundException('作品不存在');
        }

        // 检查是否是作品所有者或管理员
        const user = await this.userModel.findById(userId);
        if (
            artwork.user_id.toString() !== userId &&
            !user.roles.includes(UserRole.ADMIN)
        ) {
            throw new UnauthorizedException('无权删除该作品');
        }

        await this.artworkModel.findByIdAndDelete(artworkId);
    }

    // Obtener todos los usuarios (para administradores)
    async findAll(): Promise<User[]> {
        return await this.userModel.find().exec();
    }

    // Eliminar un usuario
    async remove(id: string): Promise<void> {
        const user = await this.userModel.findById(id);
        if (!user) {
            throw new NotFoundException('用户不存在');
        }

        // Eliminar el usuario
        await this.userModel.findByIdAndDelete(id).exec();

        // Eliminar configuraciones del usuario
        await this.userSettingModel.deleteOne({ user_id: id }).exec();

        // Opcionalmente, también se podrían eliminar las obras del usuario
        // await this.artworkModel.deleteMany({ user_id: id }).exec();
    }
} 